package com.literaryfamily.literaryfamily.myUtil;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.codec.Base64;
import com.literaryfamily.literaryfamily.exceptions.OperationException;
import com.alipay.api.response.AlipayTradeQueryResponse;

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;

/**
 * 支付宝响应解析工具类
 */
public class AlipayResponseParser {

	/**
	 * 解析支付宝交易查询响应
	 * @param response 支付宝原始响应字符串
	 * @param alipayPublicKey 支付宝公钥
	 * @param charset 字符编码
	 * @param signType 签名类型（如RSA2）
	 * @return 解析后的响应对象
	 */
	public static AlipayTradeQueryResponse parseTradeQueryResponse(
			String response,
			String alipayPublicKey,
			String charset,
			String signType) {

		// 将响应字符串转换为JSON对象
		JSONObject responseJson = JSON.parseObject(response);

		// 获取响应内容和签名
		String responseNode = "alipay_trade_query_response";
		String responseContent = responseJson.getString(responseNode);
		String sign = responseJson.getString("sign");

		// 验证签名
		try {
			if (!verifySignature(responseContent, sign, alipayPublicKey, charset, signType)) {
				throw new OperationException("支付宝响应签名验证失败");
			}
		} catch (Exception e) {
			LogUtil.error(AlipayResponseParser.class, e);
			LogUtil.error(AlipayResponseParser.class, "支付宝响应签名验证失败");
			throw new OperationException("支付宝响应签名验证失败");
		}

		// 解析响应内容
		AlipayTradeQueryResponse queryResponse = JSON.parseObject(responseContent, AlipayTradeQueryResponse.class);

		// 检查业务响应码
		if (!"10000".equals(queryResponse.getCode())) {
			throw new OperationException(queryResponse.getSubMsg());
		}

		return queryResponse;
	}

	/**
	 * 验证签名
	 * @param content 待验签内容
	 * @param sign 签名
	 * @param publicKey 支付宝公钥
	 * @param charset 字符编码
	 * @param signType 签名类型
	 * @return 验签结果
	 * @throws Exception 验签异常
	 */
	private static boolean verifySignature(
			String content,
			String sign,
			String publicKey,
			String charset,
			String signType) throws Exception {

		if (StringUtil.isNull(publicKey) || StringUtil.isNull(signType)) {
			throw new RuntimeException("支付宝公钥或签名类型未设置");
		}
// 处理公钥格式（去除开头结尾的标记和换行符）
		String formattedPublicKey = publicKey
				.replace("-----BEGIN PUBLIC KEY-----", "")
				.replace("-----END PUBLIC KEY-----", "")
				.replaceAll("\\s+", "");

		// 解码Base64编码的公钥
		byte[] encodedKey = Base64.decodeBase64(formattedPublicKey.getBytes(StandardCharsets.UTF_8));

		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

		Signature signature = Signature.getInstance(
				"RSA2".equals(signType) ? "SHA256withRSA" : "SHA1withRSA");
		signature.initVerify(pubKey);

		// 使用指定字符集获取内容字节
		byte[] contentBytes = charset == null ?
				content.getBytes() : content.getBytes(charset);
		signature.update(contentBytes);

		// 解码Base64编码的签名
		byte[] signatureBytes = Base64.decodeBase64(sign.getBytes(StandardCharsets.UTF_8));

		return signature.verify(signatureBytes);
	}

}